package com.cicoding.tcp.server;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

/**
 * @author: zhouwenjie
 * @description: 配置管道  服务端初始化，客户端与服务器端连接一旦创建，这个类中方法就会被回调，设置出站编码器和入站解码器
 * @create: 2020-04-03 14:14
 **/
@Component
public class NettyServerChannelInitializer extends ChannelInitializer<SocketChannel> {

    @Autowired
    private NettyServerHandler nettyServerHandler;

    @Autowired
    private HeartBeatServerHandler heartBeatServerHandler;

    @Override
    protected void initChannel(SocketChannel ch) {
        ChannelPipeline pipeline = ch.pipeline();
        //数据传输规则，防止粘包（客户端和服务端发送的消息结尾必须都要带上@_）
        String delimiter = "$";
        //设置心跳机制 0永不超时,三个参数分别代表 读超时，写超时，读写超时
        pipeline.addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS));
        //限制每次数据传输的长度，防止违法大数据攻击，放在编码器上边
        pipeline.addLast(new DelimiterBasedFrameDecoder(1024 * 8, Unpooled.wrappedBuffer(delimiter.getBytes())));
        //通过换行符，即\n或者\r\n对数据进行处理  System.getProperty("line.separator")
        //pipeline.addLast(new LineBasedFrameDecoder(1024));
        pipeline.addLast(new StringDecoder(Charset.forName("UTF-8")));
        pipeline.addLast(new StringEncoder(Charset.forName("UTF-8")));
        //一定在编码器下边，否则不生效
        pipeline.addLast(new DelimiterBasedFrameEncoder(delimiter));
        //心跳放在正常handler前边，先走心跳处理器
        pipeline.addLast(heartBeatServerHandler);
        pipeline.addLast(nettyServerHandler);
    }
}
